/**
 * 游戏对象管理系统
 * 包含玩家、怪物、物品等游戏对象的类定义
 */

import { GAME_CONSTANTS, DIRECTIONS, COLORS } from './constants.js';
import { MathUtils, GameUtils, NotificationUtils } from './utils.js';
import { MONSTER_DATA, SKILL_DATA } from './data.js';

/**
 * 基础游戏对象类
 */
export class GameObject {
    constructor(x, y) {
        this.x = x || 0;
        this.y = y || 0;
        this.id = this.generateId();
        this.active = true;
        this.created = Date.now();
    }

    /**
     * 生成唯一ID
     * @returns {string}
     */
    generateId() {
        return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 更新对象
     * @param {number} deltaTime 
     */
    update(deltaTime) {
        // 基类更新逻辑
    }

    /**
     * 渲染对象
     * @param {CanvasRenderingContext2D} ctx 
     * @param {object} camera 
     */
    render(ctx, camera) {
        // 基类渲染逻辑
    }

    /**
     * 销毁对象
     */
    destroy() {
        this.active = false;
    }

    /**
     * 获取边界框
     * @returns {object}
     */
    getBounds() {
        return {
            x: this.x - GAME_CONSTANTS.TILE_SIZE / 2,
            y: this.y - GAME_CONSTANTS.TILE_SIZE / 2,
            width: GAME_CONSTANTS.TILE_SIZE,
            height: GAME_CONSTANTS.TILE_SIZE
        };
    }

    /**
     * 检查与另一个对象的碰撞
     * @param {GameObject} other 
     * @returns {boolean}
     */
    checkCollision(other) {
        return GameUtils.checkRectCollision(this.getBounds(), other.getBounds());
    }
}

/**
 * 玩家类
 */
export class Player extends GameObject {
    constructor(x, y, gameState) {
        super(x, y);
        this.gameState = gameState;
        this.direction = DIRECTIONS.DOWN;
        this.moving = false;
        this.speed = GAME_CONSTANTS.PLAYER_SPEED;
        
        // 基础属性
        this.level = 1;
        this.exp = 0;
        this.maxExp = 100;
        this.health = 100;
        this.maxHealth = 100;
        this.mana = 100;
        this.maxMana = 100;
        this.damage = 10;
        this.defense = 5;
        
        // 装备和背包
        this.inventory = [];
        this.equipment = {
            weapon: null,
            chest: null,
            rings: []
        };
        
        // 技能
        this.skills = { ...SKILL_DATA };
        
        // 状态
        this.inCombat = false;
        this.lastCombatTime = 0;
        
        // 效果
        this.statusEffects = [];
    }

    /**
     * 移动玩家
     * @param {number} deltaX 
     * @param {number} deltaY 
     * @param {GameMap} currentMap 
     */
    move(deltaX, deltaY, currentMap) {
        if (!currentMap) return;

        const newX = this.x + deltaX * this.speed;
        const newY = this.y + deltaY * this.speed;
        
        // 检查地图边界和可走性
        const tileX = GameUtils.pixelToTile(newX);
        const tileY = GameUtils.pixelToTile(newY);
        
        if (currentMap.isWalkable(tileX, tileY)) {
            this.x = newX;
            this.y = newY;
            this.moving = true;
            
            // 更新方向
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                this.direction = deltaX > 0 ? DIRECTIONS.RIGHT : DIRECTIONS.LEFT;
            } else if (deltaY !== 0) {
                this.direction = deltaY > 0 ? DIRECTIONS.DOWN : DIRECTIONS.UP;
            }
        }
    }

    /**
     * 停止移动
     */
    stopMoving() {
        this.moving = false;
    }

    /**
     * 获得经验值
     * @param {number} amount 
     */
    gainExp(amount) {
        this.exp += amount;
        
        // 检查升级
        while (this.exp >= this.maxExp) {
            this.levelUp();
        }
    }

    /**
     * 升级
     */
    levelUp() {
        this.level++;
        this.exp -= this.maxExp;
        this.maxExp = GameUtils.calculateExpForLevel(this.level);
        
        // 属性提升
        const healthIncrease = 20;
        const manaIncrease = 10;
        const damageIncrease = 5;
        const defenseIncrease = 2;
        
        this.maxHealth += healthIncrease;
        this.health = this.maxHealth; // 升级时恢复满血
        this.maxMana += manaIncrease;
        this.mana = this.maxMana; // 升级时恢复满蓝
        this.damage += damageIncrease;
        this.defense += defenseIncrease;
        
        NotificationUtils.showNotification(
            `升级了！等级 ${this.level}`, 
            'success'
        );
        
        console.log(`升级到 ${this.level} 级！属性提升：血量+${healthIncrease}，魔法+${manaIncrease}，攻击+${damageIncrease}，防御+${defenseIncrease}`);
    }

    /**
     * 受到伤害
     * @param {number} damage 
     * @returns {number} 实际伤害
     */
    takeDamage(damage) {
        const actualDamage = Math.max(1, damage - this.defense);
        this.health = Math.max(0, this.health - actualDamage);
        
        if (this.health <= 0) {
            this.onDeath();
        }
        
        return actualDamage;
    }

    /**
     * 恢复生命值
     * @param {number} amount 
     */
    heal(amount) {
        const actualHealing = Math.min(amount, this.maxHealth - this.health);
        this.health += actualHealing;
        return actualHealing;
    }

    /**
     * 消耗魔法值
     * @param {number} amount 
     * @returns {boolean} 是否成功消耗
     */
    consumeMana(amount) {
        if (this.mana >= amount) {
            this.mana -= amount;
            return true;
        }
        return false;
    }

    /**
     * 恢复魔法值
     * @param {number} amount 
     */
    restoreMana(amount) {
        const actualRestore = Math.min(amount, this.maxMana - this.mana);
        this.mana += actualRestore;
        return actualRestore;
    }

    /**
     * 使用技能
     * @param {string} skillName 
     * @param {object} target 
     * @returns {boolean}
     */
    useSkill(skillName, target = null) {
        const skill = this.skills[skillName];
        if (!skill) return false;
        
        // 检查冷却时间
        if (skill.cooldown > 0) {
            NotificationUtils.showNotification('技能冷却中', 'warning');
            return false;
        }
        
        // 检查魔法值
        if (!this.consumeMana(skill.mana)) {
            NotificationUtils.showNotification('魔法值不足', 'warning');
            return false;
        }
        
        // 设置冷却时间
        skill.cooldown = skill.maxCooldown;
        
        // 执行技能效果
        this.executeSkillEffect(skill, target);
        
        return true;
    }

    /**
     * 执行技能效果
     * @param {object} skill 
     * @param {object} target 
     */
    executeSkillEffect(skill, target) {
        if (skill.healing > 0) {
            // 治疗技能
            const healed = this.heal(skill.healing);
            NotificationUtils.showNotification(
                `${skill.name} 恢复了 ${healed} 点生命值`, 
                'success'
            );
        }
        
        if (skill.damage > 0 && target) {
            // 伤害技能
            const damage = target.takeDamage(skill.damage);
            NotificationUtils.showNotification(
                `${skill.name} 造成了 ${damage} 点伤害`, 
                'info'
            );
        }
    }

    /**
     * 死亡处理
     */
    onDeath() {
        this.health = 1; // 防止玩家真正死亡
        NotificationUtils.showNotification('生命值过低，已自动恢复', 'warning');
        console.log('玩家生命值过低，自动恢复');
    }

    /**
     * 更新玩家状态
     * @param {number} deltaTime 
     */
    update(deltaTime) {
        super.update(deltaTime);
        
        // 更新技能冷却
        this.updateSkillCooldowns();
        
        // 更新状态效果
        this.updateStatusEffects(deltaTime);
        
        // 检查自动吃药
        this.checkAutoPotion();
    }

    /**
     * 更新技能冷却时间
     */
    updateSkillCooldowns() {
        Object.values(this.skills).forEach(skill => {
            if (skill.cooldown > 0) {
                skill.cooldown = Math.max(0, skill.cooldown - 1);
            }
        });
    }

    /**
     * 更新状态效果
     * @param {number} deltaTime 
     */
    updateStatusEffects(deltaTime) {
        this.statusEffects = this.statusEffects.filter(effect => {
            effect.duration -= deltaTime;
            return effect.duration > 0;
        });
    }

    /**
     * 检查自动吃药
     */
    checkAutoPotion() {
        const healthPercent = this.health / this.maxHealth;
        if (healthPercent <= GAME_CONSTANTS.AUTO_POTION_THRESHOLD) {
            this.tryUseHealthPotion();
        }
    }

    /**
     * 尝试使用生命药水
     */
    tryUseHealthPotion() {
        const potionIndex = this.inventory.findIndex(item => 
            item.type === 'potion' && item.healing > 0
        );
        
        if (potionIndex !== -1) {
            const potion = this.inventory[potionIndex];
            this.heal(potion.healing);
            this.inventory.splice(potionIndex, 1);
            NotificationUtils.showNotification(
                `使用了 ${potion.name}`, 
                'success'
            );
        }
    }

    /**
     * 渲染玩家
     * @param {CanvasRenderingContext2D} ctx 
     * @param {object} camera 
     */
    render(ctx, camera) {
        const screenX = this.x - camera.x;
        const screenY = this.y - camera.y;
        
        // 绘制玩家身体
        ctx.fillStyle = COLORS.PRIMARY;
        ctx.fillRect(
            screenX - GAME_CONSTANTS.TILE_SIZE / 2,
            screenY - GAME_CONSTANTS.TILE_SIZE / 2,
            GAME_CONSTANTS.TILE_SIZE,
            GAME_CONSTANTS.TILE_SIZE
        );
        
        // 绘制方向指示器
        this.renderDirectionIndicator(ctx, screenX, screenY);
    }

    /**
     * 渲染方向指示器
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} screenX 
     * @param {number} screenY 
     */
    renderDirectionIndicator(ctx, screenX, screenY) {
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        
        const offset = GAME_CONSTANTS.TILE_SIZE / 4;
        let indicatorX = screenX;
        let indicatorY = screenY;
        
        switch (this.direction) {
            case DIRECTIONS.UP:
                indicatorY -= offset;
                break;
            case DIRECTIONS.DOWN:
                indicatorY += offset;
                break;
            case DIRECTIONS.LEFT:
                indicatorX -= offset;
                break;
            case DIRECTIONS.RIGHT:
                indicatorX += offset;
                break;
        }
        
        ctx.arc(indicatorX, indicatorY, 3, 0, Math.PI * 2);
        ctx.fill();
    }
}

/**
 * 怪物类
 */
export class Monster extends GameObject {
    constructor(x, y, type, level = 1) {
        super(x, y);
        
        const baseData = MONSTER_DATA[type];
        if (!baseData) {
            throw new Error(`未知的怪物类型: ${type}`);
        }
        
        this.type = type;
        this.level = level;
        this.name = baseData.name;
        this.color = baseData.color;
        this.speed = baseData.speed || 1;
        this.dropRate = baseData.dropRate;
        
        // 根据等级缩放属性
        const levelMultiplier = 1 + (level - 1) * 0.3;
        this.maxHealth = Math.floor(baseData.health * levelMultiplier);
        this.health = this.maxHealth;
        this.damage = Math.floor(baseData.damage * levelMultiplier);
        this.exp = Math.floor(baseData.exp * levelMultiplier);
        
        // AI状态
        this.aiState = 'idle'; // idle, chase, attack, retreat
        this.target = null;
        this.lastAttackTime = 0;
        this.attackCooldown = 1000; // 1秒攻击冷却
    }

    /**
     * 受到伤害
     * @param {number} damage 
     * @returns {number} 实际伤害
     */
    takeDamage(damage) {
        const actualDamage = Math.max(1, damage);
        this.health = Math.max(0, this.health - actualDamage);
        
        if (this.health <= 0) {
            this.onDeath();
        }
        
        return actualDamage;
    }

    /**
     * 死亡处理
     */
    onDeath() {
        this.destroy();
        console.log(`${this.name} Lv.${this.level} 被击败`);
    }

    /**
     * 更新怪物AI
     * @param {number} deltaTime 
     * @param {Player} player 
     */
    updateAI(deltaTime, player) {
        if (!player || !this.active) return;
        
        const distanceToPlayer = MathUtils.distance(
            this.x, this.y, player.x, player.y
        );
        
        // 状态机
        switch (this.aiState) {
            case 'idle':
                if (distanceToPlayer < GAME_CONSTANTS.MONSTER_CHASE_RANGE) {
                    this.aiState = 'chase';
                    this.target = player;
                }
                break;
                
            case 'chase':
                if (distanceToPlayer > GAME_CONSTANTS.MONSTER_CHASE_RANGE * 1.5) {
                    this.aiState = 'idle';
                    this.target = null;
                } else if (distanceToPlayer < GAME_CONSTANTS.COMBAT_RANGE) {
                    this.aiState = 'attack';
                } else {
                    this.moveTowardsTarget(player);
                }
                break;
                
            case 'attack':
                if (distanceToPlayer > GAME_CONSTANTS.COMBAT_RANGE * 1.5) {
                    this.aiState = 'chase';
                } else {
                    this.attackTarget(player, deltaTime);
                }
                break;
        }
    }

    /**
     * 向目标移动
     * @param {Player} target 
     */
    moveTowardsTarget(target) {
        const dx = target.x - this.x;
        const dy = target.y - this.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        if (distance > 0) {
            const moveX = (dx / distance) * this.speed;
            const moveY = (dy / distance) * this.speed;
            
            this.x += moveX;
            this.y += moveY;
        }
    }

    /**
     * 攻击目标
     * @param {Player} target 
     * @param {number} deltaTime 
     */
    attackTarget(target, deltaTime) {
        const currentTime = Date.now();
        if (currentTime - this.lastAttackTime >= this.attackCooldown) {
            const damage = target.takeDamage(this.damage);
            this.lastAttackTime = currentTime;
            
            console.log(`${this.name} 攻击造成 ${damage} 点伤害`);
        }
    }

    /**
     * 更新怪物
     * @param {number} deltaTime 
     * @param {Player} player 
     */
    update(deltaTime, player) {
        super.update(deltaTime);
        this.updateAI(deltaTime, player);
    }

    /**
     * 渲染怪物
     * @param {CanvasRenderingContext2D} ctx 
     * @param {object} camera 
     */
    render(ctx, camera) {
        const screenX = this.x - camera.x;
        const screenY = this.y - camera.y;
        
        // 绘制怪物身体（带阴影效果）
        this.renderWithShadow(ctx, screenX, screenY);
        
        // 绘制名称和等级
        this.renderNameAndLevel(ctx, screenX, screenY);
        
        // 绘制血条
        this.renderHealthBar(ctx, screenX, screenY);
    }

    /**
     * 渲染带阴影的怪物身体
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} screenX 
     * @param {number} screenY 
     */
    renderWithShadow(ctx, screenX, screenY) {
        // 绘制阴影
        ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
        ctx.shadowBlur = 4;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        
        ctx.fillStyle = this.color;
        ctx.fillRect(
            screenX - GAME_CONSTANTS.TILE_SIZE / 2,
            screenY - GAME_CONSTANTS.TILE_SIZE / 2,
            GAME_CONSTANTS.TILE_SIZE,
            GAME_CONSTANTS.TILE_SIZE
        );
        
        // 重置阴影
        ctx.shadowColor = 'transparent';
        ctx.shadowBlur = 0;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
    }

    /**
     * 渲染名称和等级
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} screenX 
     * @param {number} screenY 
     */
    renderNameAndLevel(ctx, screenX, screenY) {
        // 怪物名称
        ctx.fillStyle = '#ffffff';
        ctx.font = 'bold 14px Arial';
        ctx.textAlign = 'center';
        ctx.strokeStyle = '#000000';
        ctx.lineWidth = 3;
        
        const nameY = screenY - GAME_CONSTANTS.TILE_SIZE / 2 - 30;
        ctx.strokeText(this.name, screenX, nameY);
        ctx.fillText(this.name, screenX, nameY);
        
        // 等级
        ctx.fillStyle = '#FFD700';
        ctx.font = 'bold 12px Arial';
        ctx.lineWidth = 2;
        
        const levelY = screenY - GAME_CONSTANTS.TILE_SIZE / 2 - 45;
        const levelText = `Lv.${this.level}`;
        ctx.strokeText(levelText, screenX, levelY);
        ctx.fillText(levelText, screenX, levelY);
    }

    /**
     * 渲染血条
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} screenX 
     * @param {number} screenY 
     */
    renderHealthBar(ctx, screenX, screenY) {
        const barWidth = GAME_CONSTANTS.TILE_SIZE + 8;
        const barHeight = 8;
        const barX = screenX - barWidth / 2;
        const barY = screenY - GAME_CONSTANTS.TILE_SIZE / 2 - 20;
        
        // 血条背景
        ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
        ctx.fillRect(barX - 2, barY - 2, barWidth + 4, barHeight + 4);
        
        // 血条底色
        ctx.fillStyle = '#ff0000';
        ctx.fillRect(barX, barY, barWidth, barHeight);
        
        // 血条填充
        const healthPercent = this.health / this.maxHealth;
        const fillColor = healthPercent > 0.6 ? '#00ff00' : 
                         healthPercent > 0.3 ? '#ffff00' : '#ff0000';
        
        ctx.fillStyle = fillColor;
        ctx.fillRect(barX, barY, barWidth * healthPercent, barHeight);
        
        // 血条边框
        ctx.strokeStyle = '#ffffff';
        ctx.lineWidth = 1;
        ctx.strokeRect(barX, barY, barWidth, barHeight);
        
        // 血量文字
        ctx.fillStyle = '#ffffff';
        ctx.font = 'bold 11px Arial';
        ctx.textAlign = 'center';
        ctx.strokeStyle = '#000000';
        ctx.lineWidth = 2;
        
        const healthText = `${this.health}/${this.maxHealth}`;
        const textY = screenY - GAME_CONSTANTS.TILE_SIZE / 2 - 8;
        ctx.strokeText(healthText, screenX, textY);
        ctx.fillText(healthText, screenX, textY);
    }
}

/**
 * 物品类
 */
export class Item extends GameObject {
    constructor(x, y, itemData) {
        super(x, y);
        
        Object.assign(this, itemData);
        
        // 添加物品特有属性
        this.pickupable = true;
        this.spawnTime = Date.now();
        this.bobOffset = Math.random() * Math.PI * 2; // 随机漂浮偏移
    }

    /**
     * 更新物品
     * @param {number} deltaTime 
     */
    update(deltaTime) {
        super.update(deltaTime);
        
        // 简单的漂浮动画
        const time = (Date.now() - this.spawnTime) / 1000;
        this.renderY = this.y + Math.sin(time * 2 + this.bobOffset) * 2;
    }

    /**
     * 渲染物品
     * @param {CanvasRenderingContext2D} ctx 
     * @param {object} camera 
     */
    render(ctx, camera) {
        const screenX = this.x - camera.x;
        const screenY = (this.renderY || this.y) - camera.y;
        
        // 绘制物品
        ctx.fillStyle = this.color || '#FFD700';
        ctx.fillRect(
            screenX - GAME_CONSTANTS.TILE_SIZE / 4,
            screenY - GAME_CONSTANTS.TILE_SIZE / 4,
            GAME_CONSTANTS.TILE_SIZE / 2,
            GAME_CONSTANTS.TILE_SIZE / 2
        );
        
        // 绘制发光效果
        if (this.rarity && this.rarity !== 'common') {
            this.renderGlowEffect(ctx, screenX, screenY);
        }
    }

    /**
     * 渲染发光效果
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} screenX 
     * @param {number} screenY 
     */
    renderGlowEffect(ctx, screenX, screenY) {
        const glowColors = {
            uncommon: '#1eff00',
            rare: '#0070dd',
            epic: '#a335ee',
            legendary: '#ff8000'
        };
        
        const glowColor = glowColors[this.rarity];
        if (glowColor) {
            ctx.shadowColor = glowColor;
            ctx.shadowBlur = 10;
            ctx.fillStyle = glowColor;
            ctx.globalAlpha = 0.3;
            
            ctx.fillRect(
                screenX - GAME_CONSTANTS.TILE_SIZE / 3,
                screenY - GAME_CONSTANTS.TILE_SIZE / 3,
                GAME_CONSTANTS.TILE_SIZE / 1.5,
                GAME_CONSTANTS.TILE_SIZE / 1.5
            );
            
            ctx.globalAlpha = 1;
            ctx.shadowBlur = 0;
        }
    }
}

// 所有类已通过 export class 语法单独导出
